package fr.utbm.to52.android_bibtex.model.entry;

import my.javax.swing.event.EventListenerList;
import my.util.MyObjects;
import fr.utbm.to52.android_bibtex.model.spec.FieldSpecification;
import fr.utbm.to52.android_bibtex.model.spec.FieldSpecificationEvent;
import fr.utbm.to52.android_bibtex.model.spec.FieldSpecificationListener;
import fr.utbm.to52.android_bibtex.model.spec.Month;
import fr.utbm.to52.android_bibtex.model.spec.ValueType;

public class Field implements FieldSpecificationListener {

	private final FieldSpecification specification;
	public static final String SPECIFICATION_PROPERTY_NAME = "specification";

	private Object value;
	public static final String VALUE_PROPERTY_NAME = "value";

	private final EventListenerList listeners = new EventListenerList();

	public Field(FieldSpecification specification) {
		assert specification!=null;

		this.specification = specification;
	}

	public FieldSpecification getSpecification() {
		return this.specification;
	}

	public Object getValue() {
		return this.value;
	}

	public void setValue(Object value) {
		if (!MyObjects.equals(this.value, value)) {
			Object oldValue = this.value;
			this.value = value;
			fireChange(VALUE_PROPERTY_NAME, oldValue, this.value);
		}
	}

	public String stringValue() {
		if (this.value != null) {
			switch (this.specification.getType()) {
			case MONTH:
				return ((Month) this.value).shortName();
			default:
				return this.value.toString();
			}
		}
		return "";
	}

	public void addFieldListener(FieldListener l) {
		assert l!=null;

		this.listeners.add(FieldListener.class, l);
	}

	public void removeFieldListener(FieldListener l) {
		assert l!=null;

		this.listeners.remove(FieldListener.class, l);
	}

	public FieldListener[] getFieldListeners() {
		return this.listeners.getListeners(FieldListener.class);
	}

	protected void fireChange(String propertyName, Object oldValue, Object newValue) {
		FieldEvent event = new FieldEvent(this, propertyName, oldValue, newValue);
		for (FieldListener listener : getFieldListeners()) {
			listener.fieldChanged(event);
		}
	}

	@Override
	public void fieldSpecificationChanged(FieldSpecificationEvent event) {
		FieldSpecification fieldSpecification = event.getSource();

		assert this.specification == fieldSpecification;

		if (FieldSpecification.TYPE_PROPERTY_NAME.equals(event.getPropertyName())) {
			ValueType oldType = (ValueType) event.getOldValue();
			ValueType newType = (ValueType) event.getNewValue();

			// TODO handle field specification's type change
		}

		// TODO what old/new values?
		fireChange(SPECIFICATION_PROPERTY_NAME, null, null);

		//TODO VALUE_PROPERTY_NAME
	}

}
